package jflowmap.model.graph;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import jflowmap.model.ontology.Dimension;

import com.google.common.collect.Lists;

public final class Node {
	private final Dimension dimension;
	private final Graph graph;
	
	private final Set<Edge> incomingEdges = new HashSet<Edge>();
	private final Set<Edge> outgoingEdges = new HashSet<Edge>();
	
	public Node (final Dimension dimension, final Graph graph) {
		this.dimension = dimension;
		this.graph = graph;
	}
	
	public boolean hasCoordinates() {
		return dimension.canGet("Latitude", Double.class)
			&& dimension.canGet("Longitude", Double.class);
	}
	
	public double getLatitude() {
		return dimension.get("Latitude", Double.class);
	}
	
	public double getLongitude() {
		return dimension.get("Longitude", Double.class);
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((dimension == null) ? 0 : dimension.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Node other = (Node) obj;
		if (dimension == null) {
			if (other.dimension != null)
				return false;
		} else if (!dimension.equals(other.dimension))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return dimension.getName();
	}
	
	public String getName() {
		return dimension.getName();
	}

	public void addOutgoingEdge(Edge edge) {
		outgoingEdges.add(edge);
	}

	public void addIncomingEdge(Edge edge) {
		incomingEdges.add(edge);
	}

	public Dimension getDimension() {
		return dimension;
	}

	public Graph getGraph() {
		return graph;
	}
	
	public Collection<Edge> getIncomingEdges() {
		return Collections.unmodifiableSet(incomingEdges);
	}

	public Collection<Edge> getOutgoingEdges() {
		return Collections.unmodifiableSet(outgoingEdges);
	}
	
	public List<Edge> sortIncomingEdges(final Comparator<Object> comparator) {
		final List<Edge> sorted = Lists.newArrayList(incomingEdges);
		Collections.sort(sorted, comparator);
		return sorted;
	}
}
